package com.duoqin.chat.ui;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ClipData;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.chat.Chat;
import com.duoqin.chat.utils.ChatConfig;
import com.duoqin.common.EventRecordManager;
import com.duoqin.common.utils.QNHelper;
import com.duoqin.common.utils.Utils;
import com.duoqin.emoji.EmojiInputView;
import com.duoqin.emoji.EmojiManager;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.SyncAssistantApplication;

import java.io.File;

public class ChatActivity extends ChatAbsActivity {
    public static final String INTENT_EXTRA_OPEN_ID = "openId";
    public static final String INTENT_EXTRA_NAME = "name";
    private static final int INPUT_MODE_TEXT = 0;
    private static final int INPUT_MODE_EMOJI = 1;
    private static final int INPUT_MODE_VOICE = 2;

    private MediaRecorder mMediaRecorder;

    private EditText mInputTV;
    private ImageView mEmojiButton;
    private ImageView mVoiceButton;
    private EmojiInputView mEmojiInputView;
    private TextView mVoiceText;
    private RelativeLayout mLayoutVoice;
    private RelativeLayout mLayoutCancel;
    private Dialog dialog;
    private int inputMode = INPUT_MODE_TEXT;
    private AlertDialog mDeleteAllConfirmDialog;
    private String mOpenId;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!SyncAssistantApplication.getsInstance().hasLogin()) {
            Toast.makeText(getApplicationContext(), R.string.login_required_notice,
                    Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        setContentView(R.layout.activity_chat_main);
        mOpenId = getIntent().getStringExtra(INTENT_EXTRA_OPEN_ID);
        mName = getIntent().getStringExtra(INTENT_EXTRA_NAME);
        Log.d(TAG, "ChatActivity openId = " + mOpenId + "; name = " + mName);
        if (!TextUtils.isEmpty(mName)) {
            setupTitle(mName);
        } else {
            setupTitle(getString(R.string.duoqin_chat));
        }
        mToolbar.inflateMenu(R.menu.chat_message_operation);
        mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                if(item.getItemId() == R.id.delete_all){
                    showDeleteAllConfirmDialog();
                }
                return false;
            }
        });
        mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        initView();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        CursorLoader loader = new CursorLoader(getApplicationContext(),
                Chat.Columns.CONTENT_URI, Chat.Columns.CHAT_QUERY_COLUMNS,
                Chat.Columns.NAME + "=?", new String[]{mOpenId},
                Chat.Columns.DEFAULT_SORT_ORDER);
        return loader;
    }

    @SuppressLint("ClickableViewAccessibility")
    protected void initView() {
        super.initView();
        mEmojiButton = findViewById(R.id.emoji);
        mEmojiButton.setOnClickListener(this);
        mVoiceButton = findViewById(R.id.voice);
        mVoiceText = findViewById(R.id.voice_text);
        mEmojiInputView = findViewById(R.id.emojiInputView);
        mEmojiInputView.setOnItemClickListener(new EmojiInputView.OnItemClickListener() {
            @Override
            public void onItemClick(String emojiString, int emojiIcon) {
                mInputTV.setText(EmojiManager.getInstance().getExpressionString(
                        getApplicationContext(), mInputTV.getText().toString() + emojiString,
                        getResources().getDimensionPixelSize(R.dimen.duoqin_text_size_medium)));
                mInputTV.setSelection(mInputTV.getText().length());

                //mEmojiInputView.setVisibility(View.GONE);
                //mInputTV.requestFocus();
            }
        });


        mInputTV = findViewById(R.id.input);
        mInputTV.setTag("NO_VOICEINPUT");
        mInputTV.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                setupCenterKey();
            }
        });

        mInputTV.setOnClickListener(this);

        mInputTV.post(new Runnable() {
            @Override
            public void run() {
                mInputTV.requestFocus();
            }
        });

        mVoiceText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (v.getId() == R.id.voice_text) {
                    float oldY = v.getY();
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            mVoiceText.setText(R.string.loosen_to_end);
                            mVoiceText.setBackgroundResource(R.drawable.voice_send_bg);
                            showVoiceDialog();
                            playStartBeepAndStartRecording();
                            break;
                        case MotionEvent.ACTION_UP:
                            if (Math.abs(event.getY()) - oldY > 100) {
                                stopRecordingAndCancelSendMessage();
                            } else {
                                stopRecordingAndSendMessage();
                            }
                            if (dialog != null) {
                                dialog.cancel();
                            }
                            mVoiceText.setText(R.string.hold_to_talk);
                            mVoiceText.setBackgroundResource(R.drawable.voice_edit_style);
                            break;
                        case MotionEvent.ACTION_MOVE:
                            if (Math.abs(event.getY()) - oldY > 100f) {
                                mLayoutCancel.setVisibility(View.VISIBLE);
                                mLayoutVoice.setVisibility(View.GONE);
                                mVoiceText.setText(R.string.voice_cancel_tip);
                            }else {
                                mLayoutCancel.setVisibility(View.GONE);
                                mLayoutVoice.setVisibility(View.VISIBLE);
                                mVoiceText.setText(R.string.loosen_to_end);
                            }
                            break;
                    }
                }
                return true;
            }
        });

        findViewById(R.id.send).setOnClickListener(this);
        mVoiceButton.setOnClickListener(this);

        mInputTV.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    mEmojiInputView.setVisibility(View.GONE);
                    mEmojiButton.setImageResource(R.drawable.face_new);
                }
            }
        });
        mInputTV.setOnClickListener(this);

//        mVoiceButton.setOnTouchListener(new View.OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                float oldY = v.getY();
//                if (v.getId() == R.id.voice) {
//                    switch (event.getAction()) {
//                        case MotionEvent.ACTION_DOWN:
//                            //if (mInputTV.hasFocus() && !hasTextInput()) {
//                            mInputTV.setText("");
//                            mInputTV.setHint(R.string.recording_start);
//                            playStartBeepAndStartRecording();
//                            //}
//                            break;
//                        case MotionEvent.ACTION_MOVE:
//                            Log.e("ACTION_MOVE",event.getY() + "," + oldY);
//                            float instance = Math.abs(event.getY()) - oldY;
//                            if(instance > 100){
//                                stopRecordingAndCancelSendMessage();
//                            }
//                            break;
//                        case MotionEvent.ACTION_UP:
//                            stopRecordingAndSendMessage();
//                            break;
//                        default:
//                            break;
//                    }
//                }
//                return true;
//            }
//        });
    }



    @Override
    public void onClick(View v) {
        if (R.id.send == v.getId()) {
            if (hasTextInput()) {
                int TEXT_LIMIT = 240;
                if (mInputTV.getText().length() <= TEXT_LIMIT) {
                    sendTextMessage(mInputTV.getText().toString());
                    clearAllInputAndResult();
                } else {
                    Toast.makeText(getApplicationContext(),
                            getString(R.string.text_message_count_limit, TEXT_LIMIT,
                                    mInputTV.getText().length()),
                            Toast.LENGTH_SHORT).show();
                }
            }
        }
//        else if(R.id.input == v.getId()){
//            mEmojiInputView.setVisibility(View.GONE);
//            showSoftInput();
//        }
        else if (R.id.send != v.getId()) {
            switch (inputMode) {
                case INPUT_MODE_TEXT:
                    switch (v.getId()) {
                        case R.id.voice:
                            inputMode = INPUT_MODE_VOICE;
                            mVoiceButton.setImageResource(R.drawable.keyboard);
                            mInputTV.setVisibility(View.GONE);
                            mVoiceText.setVisibility(View.VISIBLE);
                            mEmojiButton.setImageResource(R.drawable.face_new);
                            findViewById(R.id.send).setVisibility(View.GONE);
                            hideSoftInput();
                            break;
                        case R.id.emoji:
                            inputMode = INPUT_MODE_EMOJI;
                            mEmojiButton.setImageResource(R.drawable.keyboard);
                            hideSoftInput();
                            mEmojiInputView.requestFocus();
                            mEmojiInputView.setSelection(0);
                            mEmojiInputView.setVisibility(View.VISIBLE);
                            break;
                    }
                    break;
                case INPUT_MODE_VOICE:
                    switch (v.getId()) {
                        case R.id.voice:
                            inputMode = INPUT_MODE_TEXT;
                            mVoiceButton.setImageResource(R.drawable.voice_new);
                            mInputTV.setVisibility(View.VISIBLE);
                            mVoiceText.setVisibility(View.GONE);
                            showSoftInput();
                            findViewById(R.id.send).setVisibility(View.VISIBLE);
                            break;
                        case R.id.emoji:
                            inputMode = INPUT_MODE_EMOJI;
                            mEmojiButton.setImageResource(R.drawable.keyboard);
                            findViewById(R.id.send).setVisibility(View.VISIBLE);
                            hideSoftInput();
                            mEmojiInputView.setVisibility(View.VISIBLE);
                            mInputTV.setVisibility(View.VISIBLE);
                            mVoiceText.setVisibility(View.GONE);
                            mVoiceButton.setImageResource(R.drawable.voice_new);
                            break;
                    }
                    break;
                case INPUT_MODE_EMOJI:
                    switch (v.getId()) {
                        case R.id.voice:
                            inputMode = INPUT_MODE_VOICE;
                            mVoiceButton.setImageResource(R.drawable.keyboard);
                            mInputTV.setVisibility(View.GONE);
                            mVoiceText.setVisibility(View.VISIBLE);
                            mEmojiButton.setImageResource(R.drawable.face_new);
                            findViewById(R.id.send).setVisibility(View.GONE);
                            mEmojiInputView.setVisibility(View.GONE);
                            break;
                        case R.id.emoji:
                            inputMode = INPUT_MODE_TEXT;
                            mEmojiButton.setImageResource(R.drawable.face_new);
                            findViewById(R.id.send).setVisibility(View.VISIBLE);
                            showSoftInput();
                            mEmojiInputView.setVisibility(View.GONE);
                            break;
                    }
                    break;
            }
        } else {
            super.onClick(v);
        }

    }



    private void setDialogPosition(Dialog dialog){
        Window window = dialog.getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        window.setGravity(Gravity.TOP);
        params.y = 200;
        window.setAttributes(params);
    }

    private void showVoiceDialog() {
        if(dialog != null){
            dialog.dismiss();
        }
        View view = LayoutInflater.from(ChatActivity.this).inflate(R.layout.dialog_voice, null);
        mLayoutVoice = view.findViewById(R.id.layout_voice);
        mLayoutCancel  = view.findViewById(R.id.layout_cancel);
        dialog = new Dialog(ChatActivity.this, R.style.Theme_voiceDialog);
        dialog.setContentView(view);
        setDialogPosition(dialog);
        dialog.create();
        dialog.show();
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }

    @Override
    protected void prepareMenuItem(Chat chat) {
        super.prepareMenuItem(chat);
        /* move to onclick
        if (Chat.Columns.CHAT_TYPE_OUT.equalsIgnoreCase(chat.type) && !chat.sent) {
            mMenuList.add(R.string.menu_resend);
        }
        */
        mMenuList.add(R.string.menu_add_favorites);
        if (Chat.Columns.CHAT_TYPE_IN.equalsIgnoreCase(chat.type)
                && Chat.Columns.CHAT_MESSAGE_TYPE_VOICE.equalsIgnoreCase(chat.message_type)
                && !TextUtils.isEmpty(chat.message_text)) {
            mMenuList.add(R.string.menu_to_text);
        }
        if (Chat.Columns.CHAT_MESSAGE_TYPE_TEXT.equalsIgnoreCase(chat.message_type)) {
            mMenuList.add(android.R.string.copy);
        }
        mMenuList.add(R.string.menu_delete);
        //mMenuList.add(R.string.menu_delete_all);
    }
//
//    @Override
//    protected void initFeatureBar() {
//        super.initFeatureBar();
//        setupCenterKey();
//        mFeatureBarHelper.setLeftIcon(R.drawable.featurebar_emoji);
//        mFeatureBarHelper.setLeftText(R.string.emoji);
//    }

    private void setupCenterKey() {
//        if (mInputTV.hasFocus()) {
//            if (hasTextInput()) {
//                mFeatureBarHelper.setCenterIcon(R.drawable.featurebar_send);
//                mFeatureBarHelper.setCenterText(R.string.default_feature_bar_send);
//            } else {
//                mFeatureBarHelper.setCenterIcon(R.drawable.featurebar_speak);
//                mFeatureBarHelper.setCenterText(R.string.speak);
//            }
//        } else {
//            mFeatureBarHelper.setCenterIcon(R.drawable.featurebar_select);
//            mFeatureBarHelper.setCenterText(R.string.default_feature_bar_center);
//        }
    }

    private boolean hasTextInput() {
        return mInputTV != null && !TextUtils.isEmpty(mInputTV.getText());
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mDeleteAllConfirmDialog != null && mDeleteAllConfirmDialog.isShowing()) {
            mDeleteAllConfirmDialog.dismiss();
        }
        stopRecording(true);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ChatConfig.freeStorage(getApplicationContext());
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER: {
                if (mInputTV.hasFocus()) {
                    if (hasTextInput()) {
                        int TEXT_LIMIT = 240;
                        if (mInputTV.getText().length() <= TEXT_LIMIT) {
                            sendTextMessage(mInputTV.getText().toString());
                            clearAllInputAndResult();
                        } else {
                            Toast.makeText(getApplicationContext(),
                                    getString(R.string.text_message_count_limit, TEXT_LIMIT,
                                            mInputTV.getText().length()),
                                    Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        stopRecordingAndSendMessage();
                    }
                }
                break;
            }
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    protected void onCopyClicked(Chat chat) {
        super.onCopyClicked(chat);
        mClipData = ClipData.newPlainText("DuoqinChat", chat.message_text);
        mClipboardManager.setPrimaryClip(mClipData);
        Toast.makeText(getApplicationContext(), R.string.copy_success, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onRecordingTimerTick() {

//        if (mInputTV != null) {
//            mInputTV.setHint(getString(R.string.recording_length, mRecordingLength,
//                    MAX_CHAT_LENGTH));
//        }
    }

    @Override
    protected void stopRecordingAndSendMessage() {
        if (ChatConfig.mRecordingFilePath != null) {
            stopRecording(false);
            File file = new File(ChatConfig.mRecordingFilePath);
            if (file.exists()) {
                sendVoiceMessage(ChatConfig.mRecordingFilePath);
            }
        }
        clearAllInputAndResult();
    }

    private void stopRecordingAndCancelSendMessage() {
        if (ChatConfig.mRecordingFilePath != null) {
            stopRecording(true);
        }
    }

    @Override
    protected void onAudioFocusLost() {
        super.onAudioFocusLost();
        stopRecording(true);
    }

    protected void clearAllInputAndResult() {
        mInputTV.setText("");
        //mInputTV.setHint(R.string.input_text_or_speach_tips);
        ChatConfig.mRecordingFilePath = null;
    }

    protected void playStartBeepAndStartRecording() {
        startRecording();
        mRecordingLength = 0;
        mHandler.sendEmptyMessageDelayed(MSG_SPEECH_RECORDING_TIMER, 1000);
    }

    private void startRecording() {
        if (null == mMediaRecorder) {
            mMediaRecorder = new MediaRecorder();
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mMediaRecorder.setOutputFile(ChatConfig.getRecordingFilePath());
        }

        try {
            mMediaRecorder.prepare();
            mMediaRecorder.start();
            Log.d(TAG, "startRecording");
        } catch (Exception e) {
            e.printStackTrace();
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
    }

    private void stopRecording(boolean deleteFile) {
        mHandler.removeMessages(MSG_SPEECH_RECORDING_TIMER);
        if (mMediaRecorder != null) {
            try {
                mMediaRecorder.stop();
                Log.d(TAG, "stopRecording");
            } catch (Exception e) {
                e.printStackTrace();
            }
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
        if (deleteFile) {
            ChatConfig.deleteRecordingFile();
        }
    }

    private void sendTextMessage(String text) {
        if (TextUtils.isEmpty(text)) return;

        Chat chat = new Chat(mOpenId);
        chat.message_type = Chat.Columns.CHAT_MESSAGE_TYPE_TEXT;
        chat.message_text = text;
        Uri uri = Chat.insert(getContentResolver(), chat);
        Log.d(TAG, "sendTextMessage " + text + "; " + uri);
        if (uri != null) {
            mGuardServiceManager.sendChatMessage(uri.getLastPathSegment());
            mHandler.sendEmptyMessageDelayed(MSG_UPDATE_UI, SEND_TIMEOUT);
            EventRecordManager.getInstance(getApplicationContext()).onEvent("CHAT",
                    chat.message_type);
        }
    }

    private void sendVoiceMessage(String filePath) {
        if (TextUtils.isEmpty(filePath)) return;
        Log.d(TAG, "sendVoiceMessage " + filePath);

        File file = new File(filePath);
        if (file.exists()) {
            Chat chat = new Chat(mOpenId);
            chat.message_type = Chat.Columns.CHAT_MESSAGE_TYPE_VOICE;
            chat.media_path = filePath;
            chat.server_media_path = ChatConfig.getServerMediaPath(this, chat);
            chat.voice_length = Utils.getVoiceDuration(chat.media_path);
            Uri uri = Chat.insert(getContentResolver(), chat);
            if (uri != null) {
                chat.id = Long.parseLong(uri.getLastPathSegment());
                QNHelper.getsQNInstance(mHandler).uploadFile(file, chat,
                        chat.server_media_path.substring(
                                chat.server_media_path.lastIndexOf("/") + 1));
            }
            Log.d(TAG, "sendVoiceMessage " + chat.id + "; server_media_path "
                    + chat.server_media_path);
        }
    }

    @Override
    protected void sendChatMessage(Chat chat) {
        super.sendChatMessage(chat);
        Log.e(TAG, "sendChatMessage " + chat.id);
        mGuardServiceManager.sendChatMessage(chat.id + "");
        mHandler.sendEmptyMessageDelayed(MSG_UPDATE_UI, SEND_TIMEOUT);
    }


    private void hideSoftInput() {
        Log.i("hideSoftInput", "mQrCodeView");
        View view = getCurrentFocus();
        if (view != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
            Log.i("hideSoftInput", "mQrCodeView2");
        }
    }

    private void showSoftInput() {
        mInputTV.requestFocus();
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.showSoftInput(mInputTV, InputMethodManager.SHOW_IMPLICIT);
    }

    private void showDeleteAllConfirmDialog() {
        android.app.AlertDialog.Builder builder = new AlertDialog.Builder(this)
                .setMessage(R.string.delete_all_confirm_notice)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Chat.deleteAll(getContentResolver(), Chat.Columns.CONTENT_URI);
                    }
                })
                .setNegativeButton(android.R.string.cancel, null);
        mDeleteAllConfirmDialog = builder.create();
        mDeleteAllConfirmDialog.show();
    }

}
